package com.tanhua.server.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.common.mapper.UserInfoMapper;
import com.tanhua.common.pojo.User;
import com.tanhua.common.pojo.UserInfo;
import com.tanhua.common.service.PicUploadService;
import com.tanhua.common.utils.UserThreadLocal;
import com.tanhua.common.vo.PageResult;
import com.tanhua.common.vo.PicUploadResult;
import com.tanhua.dubbo.server.api.SelectFriends;
import com.tanhua.dubbo.server.api.VideoApi;
import com.tanhua.dubbo.server.enums.CommentType;
import com.tanhua.dubbo.server.enums.Ttype;
import com.tanhua.dubbo.server.pojo.Video;
import com.tanhua.server.vo.VideoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author LOVE
 */
@Service
public class VideoService {

    @Autowired
    private PicUploadService picUploadService;

    /**
     * 快速文件存储客户端来自依赖
     */
    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Reference(version = "1")
    private VideoApi videoApi;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Reference(version = "1")
    private SelectFriends selectFriends;

    @Autowired
    public QuanZiService quanZiService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 上传视频
     *
     * @param map 视频，视频图片
     */
    public ResponseEntity<String> saveVideo(Map<String, MultipartFile> map) {
        //视频图片
        MultipartFile videoThumbnail = map.get("videoThumbnail");
        //视频
        MultipartFile videoFile = map.get("videoFile");
        if (videoThumbnail.isEmpty() && videoFile.isEmpty()) {
            return ResponseEntity.ok("视频或图片不存在");
        }
        try {
            //图片上传
            PicUploadResult upload = picUploadService.upload(videoThumbnail);
            //判断属性是否为null,只要有null就为true
            if (BeanUtil.hasNullField(upload, "response")) {
                return ResponseEntity.ok("图片上传失败!");
            }

            //视频上传
            StorePath storePath = fastFileStorageClient.uploadFile(videoFile.getInputStream(), videoFile.getSize(), videoFile.getOriginalFilename(), null);
            if (storePath.getPath() == null) {
                return ResponseEntity.ok("视频上传失败!");
            }

            //数据封装
            Video video = new Video();
            video.setUserId(UserThreadLocal.get().getId());
            video.setPicUrl(upload.getName());
            video.setVideoUrl(storePath.getPath());
            video.setSeeType(1);
            video.setLocationName("珠穆朗玛峰");
            video.setLatitude("99999999999");
            video.setLongitude("99999999999");

            //添加到数据库
            Boolean aBoolean = videoApi.saveVideo(video);
            if (aBoolean) {
                return ResponseEntity.ok("成功");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseEntity.ok("错误");
    }

    /**
     * 视频列表显示
     *
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult videoListDisplay(Integer page, Integer pageSize) {
        try {
            //获取userID
            User user = UserThreadLocal.get();
            //调用dubbo来获取推荐列表数据
            List<Video> videos = videoApi.queryVideoList(user.getId(), page, pageSize);
            //将userid封装到一个新集合中
            List<Object> userId = CollUtil.getFieldValues(videos, "userId");

            //通过mysql查询出视频的用户的信息
            List<UserInfo> userInfos = userInfoMapper.selectList(new QueryWrapper<UserInfo>().in("user_id", userId));

            //userid为键,userInfo对象为值
            Map<Long, UserInfo> userInfoMap = userInfos.stream().collect(Collectors.toMap(UserInfo::getUserId, Function.identity()));

            //创建返回前端实体类
            VideoVo videoVo;

            //数据封装
            List<VideoVo> videoVos = new ArrayList<>();
            for (Video video : videos) {
                videoVo = new VideoVo();
                //视频封面
                videoVo.setCover(video.getPicUrl());
                //视频id
                videoVo.setId(video.getId().toHexString());
                //视频
                videoVo.setVideoUrl(video.getVideoUrl());
                //是否点赞
                videoVo.setHasLiked(selectFriends.getWhetherItIsTrue(video.getId().toHexString(), user.getId(), CommentType.LIKE) ? 1 : 0);
                //点赞数
                videoVo.setLikeCount(selectFriends.queryLikeCount(video.getId().toHexString(), CommentType.LIKE).intValue());
                //评论数量
                videoVo.setCommentCount(selectFriends.queryLikeCount(video.getId().toHexString(), CommentType.COMMENT).intValue());
                //是否关注
                videoVo.setHasFocus(queryWhetherToFollow(video.getUserId(), user.getId()));
                //视频的用户的id
                videoVo.setUserId(video.getUserId());
                //签名
                videoVo.setSignature("我叫马牛逼!");
                //昵称
                videoVo.setNickname(userInfoMap.get(videoVo.getUserId()).getNickName());
                //头像
                videoVo.setAvatar(userInfoMap.get(videoVo.getUserId()).getLogo());

                videoVos.add(videoVo);
            }

            //降序排序
            videoVos.sort((o1, o2) -> o2.getLikeCount() - o1.getLikeCount());

            //数据再封装,反回前端
            return new PageResult(100, pageSize, 100, page, videoVos);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 视频点赞
     *
     * @param videoId 视频id
     */
    public Boolean videoLikes(String videoId) {
        try {
            //获取userid
            User user = UserThreadLocal.get();

            //进行点赞操作
            Boolean aBoolean = selectFriends.likeLoveComment(user.getId(), videoId, CommentType.LIKE, null);
            if (aBoolean) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 取消视频点赞
     *
     * @param videoId 视频id
     * @return
     */
    public Boolean unlikeVideo(String videoId) {
        try {
            //获取userid
            User user = UserThreadLocal.get();

            //进行取消点赞操作
            Boolean aBoolean = selectFriends.disLikeComment(user.getId(), videoId, CommentType.LIKE, null);
            if (aBoolean) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获取评论列表
     *
     * @param videoId  视频id
     * @param page     当前页
     * @param pagesize 当前页数据条数
     * @return 数据
     */
    public PageResult getAListOfComments(String videoId, Integer page, Integer pagesize) {
        //获取评论列表
        return quanZiService.findComments(videoId, page, pagesize);
    }

    /**
     * 发表评论
     *
     * @param videoId 视频id
     * @param comment 评论
     * @return
     */
    public ResponseEntity<?> postAComment(String videoId, String comment) {
        try {
            //发表评论
            return quanZiService.commentsSubmit(videoId, comment);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 评论点赞
     *
     * @param videoId 视频id
     */
    public Boolean commentLike(String videoId) {
        try {
            //进行点赞
            Long aLong = quanZiService.arbitrarilyComment(videoId, CommentType.LIKE, Ttype.INSERT);
            if (aLong != null) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 取消点赞
     *
     * @param videoId 视频id
     * @return 是否成功
     */
    public Boolean cancelCommentLike(String videoId) {
        try {
            //进行点赞
            Long aLong = quanZiService.arbitrarilyComment(videoId, CommentType.LIKE, Ttype.REMOVE);
            if (aLong != null) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 关注
     * @param toUserid 被关注的用户的id
     * @return
     */
    public Boolean attention(String toUserid) {
        try {
            //获取userid
            User user = UserThreadLocal.get();

            //查询是否已经关注
            Integer integer = queryWhetherToFollow(Long.valueOf(toUserid), user.getId());
            if (integer == 1) {
                return true;
            }

            //未关注进行关注,将数据保存到MongoDB中
            Boolean whetherToFollow = videoApi.attention(toUserid, user.getId());
            if (!whetherToFollow) {
                return false;
            }

            //修改Redis中的数据
            redisTemplate.opsForHash().put(getRedisKey(Long.valueOf(toUserid)),getHashKey(user.getId()),"1");
            return true;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 取消关注
     * @param toUserid 被关注的用户的id
     * @return 是否关注
     */
    public Boolean unsubscribe(String toUserid) {
        try {
            //获取userid
            User user = UserThreadLocal.get();

            //查询是否已经关注
            Integer integer = queryWhetherToFollow(Long.valueOf(toUserid), user.getId());
            if (integer == 0) {
                return true;
            }

            //关注,删除关注数据
            Boolean whetherToFollow = videoApi.unsubscribe(toUserid, user.getId());
            if (!whetherToFollow) {
                return false;
            }

            //修改Redis中的数据
            redisTemplate.opsForHash().put(getRedisKey(Long.valueOf(toUserid)),getHashKey(user.getId()),"0");
            return true;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 查询是否关注
     *
     * @param toUserId 动态用户id
     * @param userId   用户id
     * @return
     */

    public Integer queryWhetherToFollow(Long toUserId, Long userId) {
        //去Redis中查询是否关注
        Object o = redisTemplate.opsForHash().get(getRedisKey(toUserId),getHashKey(userId));

        //等于1为关注
        if (o != null && "1".equals(o.toString())) {
            return 1;
        }
        return 0;
    }

    //获得Redis中被关注的的用户的key
    private String getRedisKey(Long toUserId){
       return "FOLLOWED_USER"+toUserId;
    }

    //获得Redis中谁关注的key
    private String getHashKey(Long userId){
        return "FOLLOW_USERS"+userId;
    }
}
